package pers.tong.weiliao.web.websocket;

import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pers.tong.weiliao.model.vo.ResponseJson;
import pers.tong.weiliao.service.WeiliaoService;
import pers.tong.weiliao.util.Constant;

@Component
@Sharable
public class WebSocketServerHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServerHandler.class);

    @Autowired
    private WeiliaoService weiliaoService;

    /**
     * 描述： 读取完连接的消息后，对消息进行处理
     * 这里主要是处理WebSocket请求
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame msg) throws Exception {
        handlerWebSocketFrame(ctx, msg);
    }

    /**
     * 描述： 处理WebSocketFrame
     *
     * @param ctx
     * @param frame
     */
    private void handlerWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
        // 关闭请求
        if (frame instanceof CloseWebSocketFrame) {
            WebSocketServerHandshaker handshaker = Constant.webSocketHandshakerMap
                    .get(ctx.channel().id().asLongText());
            if (handshaker == null) {
                sendErrorMessage(ctx, "不存在的客户端连接！");
            } else {
                handshaker.close(ctx.channel(), ((CloseWebSocketFrame) frame).retain());
            }
            return;
        }

        // ping请求
        if (frame instanceof PingWebSocketFrame) {
            ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
            return;
        }

        // 只支持文本格式，不支持二进制信息
        if (!(frame instanceof TextWebSocketFrame)) {
            sendErrorMessage(ctx, "仅支持文本(Text)格式，不支持二进制信息");
        }

        // 客户端发送过来的信息
        String request = ((TextWebSocketFrame) frame).text();
        LOGGER.info("客户端收到新信息：" + request);
        JSONObject param = null;
        try {
            param = JSONObject.parseObject(request);
        } catch (Exception e) {
            sendErrorMessage(ctx, "JSON字符串转换出错!");
            e.printStackTrace();
        }
        if (param == null) {
            sendErrorMessage(ctx, "参数为空！");
            return;
        }

        String type = (String) param.get("type");
        switch (type) {
            case "REGISTER":
                weiliaoService.register(param, ctx);
                break;
            case "SINGLE_SENDING":
                weiliaoService.singleSend(param, ctx);
                break;
            case "GROUP_SENDING":
                weiliaoService.groupSend(param, ctx);
                break;
            case "FILE_MSG_SINGLE_SENDING":
                weiliaoService.FileMsgSingleSend(param, ctx);
                break;
            case "FILE_MSG_GROUP_SENDING":
                weiliaoService.FileMsgGroupSend(param, ctx);
                break;
            default:
                weiliaoService.typeError(ctx);
                break;
        }
    }

    /**
     * 描述：客户端断开连接
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        weiliaoService.remove(ctx);
    }

    /**
     * 描述：异常处理关闭channel
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    private void sendErrorMessage(ChannelHandlerContext ctx, String errorMsg) {
        String responseJson = new ResponseJson().error(errorMsg).toString();
        ctx.channel().writeAndFlush(new TextWebSocketFrame(responseJson));
    }
}
